#ifndef __INCgenericCallerh
#define __INCgenericCallerh
#include <type_traits> 
#include <utility>
#include <log.h>

template <typename ObjectType>
class GenericCaller {
public:
    explicit GenericCaller(ObjectType* obj) : obj_(obj) {}

    template <typename... Args>
    void call(void (ObjectType::* func)(Args...), Args&&... args)
    {
        if (checkObjectValidity())
        {
            (obj_->*func)(std::forward<Args>(args)...);
        }
    }

    template <typename RetType, typename... Args>
    RetType call(RetType(ObjectType::* func)(Args...), Args&&... args)
    {
        if (checkObjectValidity())
        {
            return (obj_->*func)(std::forward<Args>(args)...);
        }
        return RetType{};
    }

    template <typename Func, typename... Args>
    void call(Func&& func, Args&&... args)
    {
        if (checkObjectValidity())
        {
            std::forward<Func>(func)(obj_, std::forward<Args>(args)...);
        }
    }

    template <typename RetType, typename Func, typename... Args>
    RetType call(Func&& func, Args&&... args)
    {
        if (checkObjectValidity())
        {
            return std::forward<Func>(func)(obj_, std::forward<Args>(args)...);
        }
        return RetType();
    }

private:
    ObjectType* obj_;

    bool checkObjectValidity() const
    {
        if (obj_ == nullptr)
        {
            LOG_ERROR("Object pointer is null, cannot call function");
            return false;
        }
        return true;
    }
};

#endif
